package com.ljx.blog.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljx.blog.article.domain.vo.resp.ThemeResp;
import com.ljx.blog.article.service.ThemeService;
import com.ljx.blog.common.domain.vo.resp.PageResp;
import com.ljx.blog.common.enums.CommonStatusTypeEnum;
import com.ljx.blog.common.exception.ApiException;
import com.ljx.blog.security.util.UserUtil;
import com.ljx.blog.user.domain.dto.UserFlagDto;
import com.ljx.blog.user.domain.entity.Tenant;
import com.ljx.blog.user.domain.entity.User;
import com.ljx.blog.user.domain.vo.req.TenantPageReq;
import com.ljx.blog.user.domain.vo.req.TenantSubmitReq;
import com.ljx.blog.user.domain.vo.req.UserPageReq;
import com.ljx.blog.user.domain.vo.resp.TenantResp;
import com.ljx.blog.user.domain.vo.resp.UserResp;
import com.ljx.blog.user.event.TenantSubmitEvent;
import com.ljx.blog.user.mapper.TenantMapper;
import com.ljx.blog.user.service.RoleService;
import com.ljx.blog.user.service.TenantService;
import com.ljx.blog.user.service.UserService;
import com.ljx.blog.user.typehandler.custom.ThemeRespList;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class TenantServiceImpl extends ServiceImpl<TenantMapper, Tenant> implements TenantService {

    @Autowired
    private TenantMapper tenantMapper;

    @Autowired
    private ThemeService themeService;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Override
    public Long getTenantIdByCode(String tenantCode) {
        if (StrUtil.isEmpty(tenantCode)){
            return null;
        }
        Tenant tenant = tenantMapper.selectOne(new LambdaQueryWrapper<Tenant>()
                .eq(Tenant::getCode, tenantCode)
                .eq(Tenant::getStatus, CommonStatusTypeEnum.NORMAL.getKey()));
        if (Objects.isNull(tenant)){
            return null;
        }
        return tenant.getId();
    }

    @Override
    public TenantResp getInfoByCode(String code) {
        Tenant tenant = tenantMapper.selectOne(new LambdaQueryWrapper<Tenant>()
                .eq(Tenant::getCode, code)
                .eq(Tenant::getStatus, CommonStatusTypeEnum.NORMAL.getKey()));
        return BeanUtil.copyProperties(tenant, TenantResp.class);
    }

    @Override
    @Transactional
    public TenantResp submit(TenantSubmitReq req) {
        Tenant tenant;
        if (Objects.isNull(req.getId()) && UserUtil.checkIsPlatform()){
            tenant = BeanUtil.copyProperties(req, Tenant.class);
            List<ThemeResp> themes = themeService.init();
            tenant.setThemeDetails(new ThemeRespList(themes));
            tenantMapper.insert(tenant);
            applicationEventPublisher.publishEvent(new TenantSubmitEvent(this, tenant.getId()));
        } else {
            if (Objects.isNull(req.getId())){
                req.setId(UserUtil.tryToGetTenantId());
            }
            tenant = tenantMapper.selectById(req.getId());
            copyReqParamsToTenant(req, tenant);
            BeanUtils.copyProperties(req, tenant);
            tenantMapper.updateById(tenant);
        }
        return getInfo(tenant.getId());
    }

    private void copyReqParamsToTenant(TenantSubmitReq req, Tenant tenant) {
        if (CollUtil.isEmpty(req.getThemeDetails())){
            return;
        }
        if (Objects.nonNull(req.getName())){
            tenant.setName(req.getName());
        }
        Map<Long, ThemeResp> themeMap = req.getThemeDetails().stream().collect(Collectors.toMap(ThemeResp::getId, Function.identity()));
        List<ThemeResp> resThemeList = tenant.getThemeDetails().stream().map(item -> {
            if (themeMap.containsKey(item.getId())) {
                ThemeResp themeResp = themeMap.get(item.getId());
                BeanUtils.copyProperties(themeResp, item);
            }
            return item;
        }).collect(Collectors.toList());
        tenant.setThemeDetails(new ThemeRespList(resThemeList));
    }

    @Override
    public TenantResp getInfo(Long tenantId) {
        Tenant tenant = tenantMapper.selectById(tenantId);
        return BeanUtil.copyProperties(tenant, TenantResp.class);
    }

    @Override
    public PageResp<Tenant> getPage(TenantPageReq req) {
        LambdaQueryWrapper<Tenant> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull(req.getKey())){
            lambdaQueryWrapper.like(Tenant::getName, req.getKey());
        }
        Page<Tenant> page = tenantMapper.selectPage(new Page<>(req.getCurrPage(), req.getPageSize()), lambdaQueryWrapper);
        return PageResp.<Tenant>builder()
                .list(page.getRecords())
                .total(page.getTotal())
                .build();
    }

    @Override
    public PageResp<User> getUserPage(UserPageReq req) {
        Boolean isTenantAdmin = UserUtil.checkIsTenantAdmin();
        Boolean isSuperUser = UserUtil.checkIsPlatform();
        if (!isTenantAdmin && !isSuperUser){
            throw new ApiException("权限不足");
        }

        UserService userService = SpringUtil.getBean(UserService.class);
        return userService.getPage(req, new UserFlagDto(isTenantAdmin, isSuperUser));
    }
}
